﻿#region Includes
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
#endregion

namespace Proyecto_XNA
{
    class SpriteAnimation : DrawableGameComponent
    {
        #region Properties

        private TimeSpan m_kGameTime;
        private SpriteBatch m_kSpriteBatch;
        private Texture2D m_kTexture;
        
        private string m_szTexturePath;
        private bool m_bPaused;
        
        private int[][] m_mFrameInfo;
        private int m_iFrameX;
        private int m_iFrameY;

        private Vector2 m_vPosition;
        public Vector2 Position
        {
            get { return m_vPosition; }
            set { m_vPosition = value; }
        }

        private int m_iFrameDelay;
        public int FrameDelay
        {
            get { return m_iFrameDelay; }
            set { m_iFrameDelay = value; }
        }

        private bool m_bLooped;
        public bool Looped
        {
            get { return m_bLooped; }
            set { m_bLooped = value; }
        }

        private int m_iFrameWidth;
        public int FrameWidth
        {
            get { return m_iFrameWidth; }
            set { m_iFrameWidth = value; }
        }

        private int m_iFrameHeight;
        public int FrameHeight
        {
            get { return m_iFrameHeight; }
            set { m_iFrameHeight = value; }
        }

        #endregion

        public SpriteAnimation(Game kGame, string szTexturePath, int iFrameWidth, int iFrameHeight,
                               int iFrameDelay, Vector2 vPosition, bool bLooped)
        :
        base(kGame)
        {
            m_bPaused = true;
            m_iFrameDelay = iFrameDelay;
            m_vPosition = vPosition;
            m_bLooped = bLooped;

            // Guardo los datos de la textura
            m_iFrameHeight = iFrameHeight;
            m_iFrameWidth = iFrameWidth;
            m_szTexturePath = szTexturePath;
        }

        public void Play()
        {
            if (m_bPaused)
            {
                m_iFrameX = m_iFrameY = 0;
            }

            m_bPaused = false;
        }

        public void Pause()
        {
            m_bPaused = true;
        }

        public void Stop()
        {
            m_bPaused = true;
            m_iFrameX = m_iFrameY = 0;
        }

        protected override void LoadContent()
        {
            m_kSpriteBatch = new SpriteBatch(GraphicsDevice);

            m_kTexture = Game.Content.Load<Texture2D>(m_szTexturePath);

            int iRows = m_kTexture.Height / m_iFrameHeight;
            int iCols = m_kTexture.Width / m_iFrameWidth;

            m_mFrameInfo = new int[iRows][];
            for (int i = 0; i < iCols; i++)
            {
                m_mFrameInfo[i] = new int[iCols];
                for (int j = 0; j < iRows; j++)
                {
                    m_mFrameInfo[i][j] = m_iFrameDelay;
                }
            }
        }

        public override void Update(GameTime gameTime)
        {
            if (!m_bPaused)
            {
                int iDelay = m_mFrameInfo[m_iFrameX][m_iFrameY];
                if ((gameTime.TotalGameTime - m_kGameTime).TotalMilliseconds > iDelay)
                {
                    //si al final de una fila la animacion se tiene que mover que mover al siguiente cuadro,
                    //sino se movera a la siguiente columna
                    if(++m_iFrameX >= m_mFrameInfo[m_iFrameY].Length)
                    {
                        //al final de la ultima fila en una animacion no loopeada
                        if (m_iFrameY + 1 == m_mFrameInfo.Length && !m_bLooped)
                        {
                            m_bPaused = true;
                            m_iFrameX--;
                        }
                        else
                        {
                            //la animacion loopea cuando hay mas filas disponibles.
                            //nos movemos a la primera columna en la fila siguiente.
                            m_iFrameY = ++m_iFrameY % m_mFrameInfo.Length;
                            m_iFrameX = 0;
                        }
                    }
                }
                m_kGameTime = gameTime.TotalGameTime;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            m_kSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);
            m_kSpriteBatch.Draw(m_kTexture, m_vPosition,
                new Rectangle(m_iFrameX * m_iFrameWidth, m_iFrameY * m_iFrameHeight, m_iFrameWidth, m_iFrameHeight),
                Color.White);
            m_kSpriteBatch.End();
        }
    }
}
